package org.sam.swing.model;

import java.io.Serializable;
import java.time.LocalTime;
import java.util.Calendar;

import javax.swing.AbstractSpinnerModel;

/**
 * 本地时间
 * 
 * @author sam
 *
 */
public class SpinnerLocalTimeModel extends AbstractSpinnerModel implements Serializable {

	private static final long serialVersionUID = -8943597676587317878L;

	private Comparable<LocalTime> start, end;
	private LocalTime value;
	private int calendarField;

	/**
	 * 检查使用的字段
	 * 
	 * @param calendarField
	 * @return
	 */
	private boolean calendarFieldOK(int calendarField) {
		switch (calendarField) {
		case Calendar.HOUR:
		case Calendar.MINUTE:
		case Calendar.SECOND:
			return true;
		default:
			return false;
		}
	}

	/**
	 * 抄袭的SpnnierDateModel
	 * 
	 * @param value
	 *            值
	 * @param start
	 *            开始值
	 * @param end
	 *            结束值
	 * @param calendarField
	 *            初始字段
	 */
	public SpinnerLocalTimeModel(LocalTime value, Comparable<LocalTime> start, Comparable<LocalTime> end,
			int calendarField) {
		if (value == null) {
			throw new IllegalArgumentException("value is null");
		}
		if (!calendarFieldOK(calendarField)) {
			throw new IllegalArgumentException("invalid calendarField");
		}
		if (!(((start == null) || (start.compareTo(value) <= 0)) && ((end == null) || (end.compareTo(value) >= 0)))) {
			throw new IllegalArgumentException("(start <= value <= end) is false");
		}
		this.start = start;
		this.end = end;
		this.calendarField = calendarField;

		this.value = value;
	}

	/**
	 * 抄袭的SpnnierDateModel
	 */
	public SpinnerLocalTimeModel() {
		this(LocalTime.now(), null, null, Calendar.HOUR);
	}

	/**
	 * 控件最小时间
	 * 
	 * @return
	 */
	public Comparable<LocalTime> getStart() {
		return start;
	}

	/**
	 * 控件最小时间
	 * 
	 * @param start
	 */
	public void setStart(Comparable<LocalTime> start) {
		if ((start == null) ? (this.start != null) : !start.equals(this.start)) {
			this.start = start;
			fireStateChanged();
		}
	}

	/**
	 * 控件最大时间
	 * 
	 * @return
	 */
	public Comparable<LocalTime> getEnd() {
		return end;
	}

	/**
	 * 控件最大时间
	 * 
	 * @param end
	 */
	public void setEnd(Comparable<LocalTime> end) {
		if ((end == null) ? (this.end != null) : !end.equals(this.end)) {
			this.end = end;
			fireStateChanged();
		}
	}

	/**
	 * 当前编辑字段
	 * 
	 * @return
	 */
	public int getCalendarField() {
		return calendarField;
	}

	/**
	 * 当前编辑字段
	 * 
	 * @param calendarField
	 */
	public void setCalendarField(int calendarField) {
		if (!calendarFieldOK(calendarField)) {
			throw new IllegalArgumentException("invalid calendarField");
		}
		if (calendarField != this.calendarField) {
			this.calendarField = calendarField;
			fireStateChanged();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object getValue() {
		return this.value;
	}
	
	/**
	 * 返回编辑的时间
	 * @return
	 */
	public LocalTime getLoaclTime(){
		return value;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setValue(Object value) {
		if ((value == null) || !(value instanceof LocalTime)) {
			throw new IllegalArgumentException("illegal value");
		}
		if (!value.equals(this.value)) {
			this.value = (LocalTime)value;
			fireStateChanged();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object getNextValue() {
		LocalTime next = null;
		switch (calendarField) {
		case Calendar.HOUR:
			next = value.plusHours(1);
			break;
		case Calendar.MINUTE:
			next = value.plusMinutes(1);
			break;
		case Calendar.SECOND:
			next = value.plusSeconds(1);
			break;
		}
		return ((end == null) || (end.compareTo(next) >= 0)) ? next : null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object getPreviousValue() {
		LocalTime prev = null;
		switch (calendarField) {
		case Calendar.HOUR:
			prev = value.plusHours(-1);
			break;
		case Calendar.MINUTE:
			prev = value.plusMinutes(-1);
			break;
		case Calendar.SECOND:
			prev = value.plusSeconds(-1);
			break;
		}

		return ((start == null) || (start.compareTo(prev) <= 0)) ? prev : null;
	}

}
